home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / tar.gnu / sprite / RCS / create.c,v < prev    next >
Encoding:
Text File  |  1992-03-29  |  38.7 KB  |  1,773 lines

  1. head     1.5;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.5
  10. date     92.03.28.17.31.24;  author kupfer;  state Exp;
  11. branches ;
  12. next     1.4;
  13.  
  14. 1.4
  15. date     92.03.05.21.37.45;  author rab;  state Exp;
  16. branches ;
  17. next     1.3;
  18.  
  19. 1.3
  20. date     90.09.07.11.25.04;  author rab;  state Exp;
  21. branches ;
  22. next     1.2;
  23.  
  24. 1.2
  25. date     90.06.28.15.35.29;  author rab;  state Exp;
  26. branches ;
  27. next     1.1;
  28.  
  29. 1.1
  30. date     90.03.21.22.30.48;  author rab;  state Exp;
  31. branches ;
  32. next     ;
  33.  
  34.  
  35. desc
  36. @@
  37.  
  38.  
  39. 1.5
  40. log
  41. @Restructure to remove some of the ALLOW_LONG_NAMES ifdefs.  Lint.  Fix
  42. bug that was preventing hard links with "short" names from being
  43. archived.
  44. @
  45. text
  46. @/* Create a tar archive.
  47.    Copyright (C) 1988 Free Software Foundation
  48.  
  49. This file is part of GNU Tar.
  50.  
  51. GNU Tar is free software; you can redistribute it and/or modify
  52. it under the terms of the GNU General Public License as published by
  53. the Free Software Foundation; either version 1, or (at your option)
  54. any later version.
  55.  
  56. GNU Tar is distributed in the hope that it will be useful,
  57. but WITHOUT ANY WARRANTY; without even the implied warranty of
  58. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  59. GNU General Public License for more details.
  60.  
  61. You should have received a copy of the GNU General Public License
  62. along with GNU Tar; see the file COPYING.  If not, write to
  63. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  64.  
  65. /*
  66.  * Create a tar archive.
  67.  *
  68.  * Written 25 Aug 1985 by John Gilmore, ihnp4!hoptoad!gnu.
  69.  *
  70.  * @@(#)create.c 1.36 11/6/87 - gnu
  71.  *
  72.  * $Header$ SPRITE (Berkeley)
  73.  */
  74. #include <sys/types.h>
  75. #include <sys/stat.h>
  76. #include <sys/file.h>
  77. #include <stdio.h>
  78. #include <string.h>
  79. #include <sys/param.h>
  80. #include <assert.h>
  81.  
  82. /* JF: this one is my fault */
  83. /* #include "utils.h" */
  84.  
  85. #ifndef V7
  86. #include <fcntl.h>
  87. #endif
  88.  
  89. #ifndef    MSDOS
  90. #include <pwd.h>
  91. #include <grp.h>
  92. #endif
  93.  
  94. #ifdef BSD42
  95. #include <sys/dir.h>
  96. #else
  97. #ifdef MSDOS
  98. #include <sys/dir.h>
  99. #else
  100. #ifdef USG
  101. #include "dirent.h"
  102. #define direct dirent
  103. #define DP_NAMELEN(x) strlen((x)->d_name)
  104. #else
  105. /*
  106.  * FIXME: On other systems there is no standard place for the header file
  107.  * for the portable directory access routines.  Change the #include line
  108.  * below to bring it in from wherever it is.
  109.  */
  110. #include "ndir.h"
  111. #endif
  112. #endif
  113. #endif
  114.  
  115. #ifndef DP_NAMELEN
  116. #define DP_NAMELEN(x)    (x)->d_namlen
  117. #endif
  118.  
  119. #ifdef USG
  120. #include <sys/sysmacros.h>    /* major() and minor() defined here */
  121. #endif
  122.  
  123. /*
  124.  * V7 doesn't have a #define for this.
  125.  */
  126. #ifndef O_RDONLY
  127. #define    O_RDONLY    0
  128. #endif
  129.  
  130. /*
  131.  * Most people don't have a #define for this.
  132.  */
  133. #ifndef    O_BINARY
  134. #define    O_BINARY    0
  135. #endif
  136.  
  137. #include "tar.h"
  138. #include "port.h"
  139.  
  140. extern union record *head;        /* Points to current tape header */
  141. extern struct stat hstat;        /* Stat struct corresponding */
  142. extern int head_standard;        /* Tape header is in ANSI format */
  143.  
  144. /* JF */
  145. extern struct name *gnu_list_name;
  146.  
  147. /*
  148.  * If there are no symbolic links, there is no lstat().  Use stat().
  149.  */
  150. #ifndef S_IFLNK
  151. #define lstat stat
  152. #endif
  153.  
  154. extern char    *malloc();
  155. extern char    *strcpy();
  156. extern char    *strncpy();
  157. extern void    bzero();
  158. extern void    bcopy();
  159. extern int    errno;
  160.  
  161. extern void print_header();
  162.  
  163. union record *start_header();
  164. void finish_header();
  165. void finduname();
  166. void findgname();
  167. char *name_next();
  168. void to_oct();
  169. void dump_file();
  170.  
  171. static nolinks;            /* Gets set if we run out of RAM */
  172.  
  173. #ifdef __STDC__
  174. static int copy_long_name(char *name, int type);
  175. #else
  176. static int copy_long_name();
  177. #endif
  178.  
  179. static char longname[MAXPATHLEN+1];
  180.  
  181. /*
  182.  * "Scratch" space to store the information about a sparse file before
  183.  * writing the info into the header or extended header
  184.  */
  185. /* struct sp_array     *sparsearray;*/
  186.  
  187. /* number of elts storable in the sparsearray */
  188. /*int     sparse_array_size = 10;*/
  189.  
  190. void
  191. create_archive()
  192. {
  193.     register char    *p;
  194.     char *name_from_list();
  195.  
  196.     open_archive(0);        /* Open for writing */
  197.  
  198.     if(f_gnudump) {
  199.         char buf[MAXNAMLEN],*q,*bufp;
  200.  
  201.         collect_and_sort_names();
  202.  
  203.         while(p=name_from_list())
  204.             dump_file(p,-1);
  205.         /* if(!f_dironly) { */
  206.             blank_name_list();
  207.             while(p=name_from_list()) {
  208.                 strcpy(buf,p);
  209.                 if(p[strlen(p)-1]!='/')
  210.                     strcat(buf,"/");
  211.                 bufp=buf+strlen(buf);
  212.                 for(q=gnu_list_name->dir_contents;*q;q+=strlen(q)+1) {
  213.                     if(*q=='Y') {
  214.                         strcpy(bufp,q+1);
  215.                         dump_file(buf,-1);
  216.                     }
  217.                 }
  218.             }
  219.         /* } */
  220.  
  221.     } else {
  222.         while (p = name_next(1)) {
  223.             dump_file(p, -1);
  224.         }
  225.     }
  226.  
  227.     write_eot();
  228.     close_archive();
  229.     name_close();
  230. }
  231.  
  232. /*
  233.  * Dump a single file.  If it's a directory, recurse.
  234.  * Result is 1 for success, 0 for failure.
  235.  * Sets global "hstat" to stat() output for this file.
  236.  */
  237. void
  238. dump_file (p, curdev)
  239.     char    *p;            /* File name to dump */
  240.     int    curdev;            /* Device our parent dir was on */
  241. {
  242.     union record    *header;
  243.     char type;
  244.     extern char *save_name;        /* JF for multi-volume support */
  245.     extern long save_totsize;
  246.     extern long save_sizeleft;
  247.     union record    *exhdr;
  248.     char save_linkflag;
  249.     extern time_t new_time;
  250.  
  251.  
  252.     if(f_confirm && !confirm("add",p))
  253.         return;
  254.  
  255.     /*
  256.      * Use stat if following (rather than dumping) 4.2BSD's
  257.      * symbolic links.  Otherwise, use lstat (which, on non-4.2
  258.      * systems, is #define'd to stat anyway.
  259.      */
  260.     if (0 != f_follow_links? stat(p, &hstat): lstat(p, &hstat))
  261.     {
  262. badperror:
  263.         msg_perror("can't add file %s",p);
  264. badfile:
  265.         errors++;
  266.         return;
  267.     }
  268.  
  269.     /* See if we only want new files, and check if this one is too old to
  270.        put in the archive. */
  271.     if(   f_new_files
  272.        && new_time>hstat.st_mtime
  273.        && (hstat.st_mode&S_IFMT)!=S_IFDIR
  274.        && (f_new_files>1 || new_time>hstat.st_ctime)) {
  275.         if(curdev<0) {
  276.             msg("%s: is unchanged; not dumped",p);
  277.         }
  278.         return;
  279.     }
  280.  
  281.     /*
  282.      * See if we are crossing from one file system to another,
  283.      * and avoid doing so if the user only wants to dump one file system.
  284.      */
  285.     if (f_local_filesys && curdev >= 0 && curdev != hstat.st_dev) {
  286.         msg("%s: is on a different filesystem; not dumped",p);
  287.         return;
  288.     }
  289.  
  290.     /*
  291.      * Check for multiple links.
  292.      *
  293.      * We maintain a list of all such files that we've written so
  294.      * far.  Any time we see another, we check the list and
  295.      * avoid dumping the data again if we've done it once already.
  296.      */
  297.     if (hstat.st_nlink > 1) switch (hstat.st_mode & S_IFMT) {
  298.         register struct link    *lp;
  299.  
  300.     case S_IFREG:            /* Regular file */
  301. #ifdef S_IFCTG
  302.     case S_IFCTG:            /* Contigous file */
  303. #endif
  304. #ifdef S_IFCHR
  305.     case S_IFCHR:            /* Character special file */
  306. #endif
  307.  
  308. #ifdef S_IFBLK
  309.     case S_IFBLK:            /* Block     special file */
  310. #endif
  311.  
  312. #ifdef S_IFIFO
  313.     case S_IFIFO:            /* Fifo      special file */
  314. #endif
  315.  
  316.         /* First quick and dirty.  Hashing, etc later FIXME */
  317.         for (lp = linklist; lp; lp = lp->next) {
  318.             if (lp->ino == hstat.st_ino &&
  319.                 lp->dev == hstat.st_dev) {
  320.                 char *link_name = lp->name;
  321.  
  322.                 /* We found a link. */
  323.                 hstat.st_size = 0;
  324.                 header = start_header(p, &hstat);
  325.                 if (header == NULL) goto badfile;
  326.                 while(!f_absolute_paths && *link_name == '/') {
  327.                     static int link_warn = 0;
  328.  
  329.                     if (!link_warn) {
  330.                         msg("Removing leading / from absolute links");
  331.                         link_warn++;
  332.                     }
  333.                     link_name++;
  334.                 }
  335.                 header->header.linkflag = LF_LINK;
  336.                 /* 
  337.                  * BSD tar requires that the link name have 
  338.                  * a trailing null.  See the comments in 
  339.                  * start_header.
  340.                  */
  341.                 if (strlen(link_name) < NAMSIZ) {
  342.                     strcpy(header->header.linkname,
  343.                            link_name);
  344.                     finish_header(header);
  345.                 } else if (!f_long_names) {
  346.                     msg("link name ``%s'' too long.",
  347.                         link_name);
  348.                     return;
  349.                 } else {
  350.                     header->header.isextended |= XH_LINKNAME;
  351.                     strcpy(header->header.linkname,
  352.                            "LINK_TOO_LONG--CHECK_EXTENDED_HEADER");
  353.                     finish_header(header);
  354.                     copy_long_name(link_name, XH_LINKNAME);
  355.                 }
  356.         /* FIXME: Maybe remove from list after all links found? */
  357.                 return;        /* We dumped it */
  358.             }
  359.         }
  360.  
  361.         /* Not found.  Add it to the list of possible links. */
  362.         lp = (struct link *) malloc( (unsigned)
  363.             (strlen(p) + sizeof(struct link) - NAMSIZ));
  364.         if (!lp) {
  365.             if (!nolinks) {
  366.                 fprintf(stderr,
  367.     "tar: no memory for links, they will be dumped as separate files\n");
  368.                 nolinks++;
  369.             }
  370.         }
  371.         lp->ino = hstat.st_ino;
  372.         lp->dev = hstat.st_dev;
  373.         strcpy(lp->name, p);
  374.         lp->next = linklist;
  375.         linklist = lp;
  376.     }
  377.  
  378.     /*
  379.      * This is not a link to a previously dumped file, so dump it.
  380.      */
  381.     switch (hstat.st_mode & S_IFMT) {
  382.  
  383.     case S_IFREG:            /* Regular file */
  384. #ifdef S_IFCTG
  385.     case S_IFCTG:            /* Contiguous file */
  386. #endif
  387.     {
  388.         int    f;        /* File descriptor */
  389.         long    bufsize, count;
  390.         long    sizeleft;
  391.         register union record     *start;
  392.         int     header_moved;
  393.         char    isextended = 0;
  394.         int     upperbound;
  395.         int    end_nulls = 0;
  396.  
  397.         header_moved = 0;
  398.  
  399. #ifdef BSD42
  400.         if (f_sparse_files) {
  401.         /*
  402.          * JK - This is the test for sparseness: whether the
  403.          * "size" of the file matches the number of blocks
  404.          * allocated for it.  If there is a smaller number
  405.          * of blocks that would be necessary to accommodate
  406.          * a file of this size, we have a sparse file, i.e.,
  407.          * at least one of those records in the file is just
  408.          * a useless hole.
  409.          */
  410.             if (hstat.st_size - (hstat.st_blocks * RECORDSIZE) > RECORDSIZE) {
  411.                 int    filesize = hstat.st_size;
  412.                 register int i;
  413.                 
  414.                 printf("File is sparse: %s\n", p);
  415.                 header = start_header(p, &hstat);
  416.                 if (header == NULL)
  417.                     goto badfile;
  418.                 header->header.linkflag = LF_SPARSE;
  419.                 header_moved++;
  420.                 
  421.             /*
  422.              * Call the routine that figures out the
  423.              * layout of the sparse file in question.
  424.              * UPPERBOUND is the index of the last
  425.              * element of the "sparsearray," i.e.,
  426.              * the number of elements it needed to
  427.              * describe the file.
  428.              */
  429.  
  430.                 upperbound = deal_with_sparse(p, header);
  431.  
  432.             /* 
  433.              * See if we'll need an extended header
  434.              * later
  435.              */
  436.                     if (upperbound > SPARSE_IN_HDR-1)
  437.                     header->header.isextended |= XH_SPARSE_FILE;
  438.  
  439.             /*
  440.              * We store the "real" file size so
  441.              * we can show that in case someone wants
  442.              * to list the archive, i.e., tar tvf <file>.
  443.              * It might be kind of disconcerting if the
  444.              * shrunken file size was the one that showed
  445.              * up.
  446.              */
  447.                  to_oct((long) hstat.st_size, 1+12, 
  448.                         header->header.realsize);
  449.                     
  450.             /*
  451.              * This will be the new "size" of the
  452.              * file, i.e., the size of the file
  453.              * minus the records of holes that we're
  454.              * skipping over. 
  455.              */
  456.                  
  457.                 find_new_file_size(&filesize, upperbound);
  458.                 printf("File %s is now size %d\n", 
  459.                             p, filesize);
  460.                 hstat.st_size = filesize;
  461.                 to_oct((long) filesize, 1+12,
  462.                          header->header.size);
  463. /*                to_oct((long) end_nulls, 1+12, 
  464.                         header->header.ending_blanks);*/
  465.                         
  466.                 for (i = 0; i < SPARSE_IN_HDR; i++) {
  467.                     if (!sparsearray[i].numbytes)
  468.                         break;
  469.                     to_oct(sparsearray[i].offset, 1+12,
  470.                         header->header.sp[i].offset);
  471.                     to_oct(sparsearray[i].numbytes, 1+12,
  472.                         header->header.sp[i].numbytes);
  473.                 }
  474.                     
  475.             }
  476.         }
  477. #endif
  478.         
  479.         sizeleft = hstat.st_size;
  480.         /* Don't bother opening empty, world readable files. */
  481.         if (sizeleft > 0 || 0444 != (0444 & hstat.st_mode)) {
  482.             f = open(p, O_RDONLY|O_BINARY);
  483.             if (f < 0) goto badperror;
  484.         } else {
  485.             f = -1;
  486.         }
  487.  
  488.         /* If the file is sparse, we've already taken care of this */
  489.         if (!header_moved) {
  490.             header = start_header(p, &hstat);
  491.             if (header == NULL) {
  492.                 if(f>=0)
  493.                     (void)close(f);
  494.                 goto badfile;
  495.             }
  496.         }
  497. #ifdef S_IFCTG
  498.         /* Mark contiguous files, if we support them */
  499.         if (f_standard && (hstat.st_mode & S_IFMT) == S_IFCTG) {
  500.             header->header.linkflag = LF_CONTIG;
  501.         }
  502. #endif
  503.         save_linkflag = header->header.linkflag;
  504.         finish_header(header);
  505.         if (isextended) {
  506.             int     sum = 0;
  507.             register int i;
  508. /*            register union record *exhdr;*/
  509.             static int index_offset = SPARSE_IN_HDR;
  510.  
  511.     extend:        exhdr = findrec();
  512.  
  513.             if (exhdr == NULL) goto badfile;
  514.             bzero(exhdr->charptr, RECORDSIZE);
  515.             exhdr->ext_hdr.xh_type = XH_SPARSE_FILE;
  516.             for (i = 0; i < SPARSE_EXT_HDR; i++) {
  517.                 if (i+index_offset > upperbound)
  518.                     break;
  519.                 to_oct((long) sparsearray[i+index_offset].numbytes,
  520.                     1+12,
  521.                     exhdr->ext_hdr.xh_sp[i].numbytes);
  522.                 to_oct((long) sparsearray[i+index_offset].offset,
  523.                     1+12,
  524.                     exhdr->ext_hdr.xh_sp[i].offset);
  525.             }
  526.             userec(exhdr);
  527. /*            sum += i;
  528.             if (sum < upperbound)
  529.                 goto extend;*/
  530.             if (index_offset+i < upperbound) {
  531.                 index_offset += i;
  532.                 exhdr->ext_hdr.xh_isextended |= XH_SPARSE_FILE;
  533.                 goto extend;
  534.             }
  535.  
  536.         }
  537.         if (save_linkflag == LF_SPARSE) {
  538.             if (finish_sparse_file(f, &sizeleft, hstat.st_size, p))
  539.                 goto padit;
  540.         }
  541.         else
  542.           while (sizeleft > 0) {
  543.  
  544.             if(f_multivol) {   
  545.                 save_name = p;
  546.                 save_sizeleft = sizeleft;
  547.                 save_totsize = hstat.st_size;
  548.             }
  549.             start = findrec();
  550.  
  551.             bufsize = endofrecs()->charptr - start->charptr;
  552.  
  553.             if (sizeleft < bufsize) {
  554.                 /* Last read -- zero out area beyond */
  555.                 bufsize = (int)sizeleft;
  556.                 count = bufsize % RECORDSIZE;
  557.                 if (count) 
  558.                     bzero(start->charptr + sizeleft,
  559.                         (int)(RECORDSIZE - count));
  560.             }
  561.             count = read(f, start->charptr, bufsize);
  562.             if (count < 0) {
  563.                 msg_perror("read error at byte %ld, reading\
  564.  %d bytes, in file %s",  hstat.st_size - sizeleft, bufsize,p);
  565.                 goto padit;
  566.             }
  567.             sizeleft -= count;
  568.  
  569.             /* This is nonportable (the type of userec's arg). */
  570.             userec(start+(count-1)/RECORDSIZE);
  571.  
  572.             if (count == bufsize) continue;
  573.             msg( "file %s shrunk by %d bytes, padding with zeros.\n", p, sizeleft);
  574.             goto padit;        /* Short read */
  575.         }
  576.  
  577.         if(f_multivol)
  578.             save_name = 0;
  579.  
  580.         if (f >= 0)
  581.             (void)close(f);
  582.  
  583.         break;
  584.  
  585.         /*
  586.          * File shrunk or gave error, pad out tape to match
  587.          * the size we specified in the header.
  588.          */
  589.     padit:
  590.         while(sizeleft>0) {
  591.             save_sizeleft=sizeleft;
  592.             start=findrec();
  593.             bzero(start->charptr,RECORDSIZE);
  594.             userec(start);
  595.             sizeleft-=RECORDSIZE;
  596.         }
  597.         if(f_multivol)
  598.             save_name=0;
  599.         if(f>=0)
  600.             (void)close(f);
  601.         break;
  602. /*        abort(); */
  603.     }
  604.  
  605. #ifdef S_IFLNK
  606.     case S_IFLNK:            /* Symbolic link */
  607.     {
  608.         int size;
  609.         char linknamebuf[MAXPATHLEN+1]; /* +1 for null */
  610.  
  611.         hstat.st_size = 0;        /* Force 0 size on symlink */
  612.         header = start_header(p, &hstat);
  613.         if (header == NULL)
  614.             goto badfile;
  615.         size = readlink(p, linknamebuf, NAMSIZ);
  616.         if (size < 0)
  617.             goto badperror;
  618.         linknamebuf[size] = '\0';
  619.         header->header.linkflag = LF_SYMLINK;
  620.         /* 
  621.          * BSD tar requires that the link name have a trailing 
  622.          * null.  See the comments in start_header.
  623.          */
  624.         if (size < NAMSIZ) {
  625.             strcpy(header->header.linkname, linknamebuf);
  626.             finish_header(header);    /* Nothing more to do to it */
  627.         } else if (!f_long_names) {
  628.             msg("symbolic link %s too long\n",p);
  629.             break;
  630.         } else {
  631.             size = readlink(p, linknamebuf, MAXPATHLEN);
  632.             linknamebuf[size] = '\0';
  633.             header->header.isextended |= XH_LINKNAME;
  634.             strcpy(header->header.linkname,
  635.                    "LINK_TOO_LONG--CHECK_EXTENDED_HEADER");
  636.             finish_header(header);
  637.             copy_long_name(linknamebuf, XH_LINKNAME);
  638.         }
  639.     }
  640.         break;
  641. #endif
  642. #ifdef S_IFRLNK
  643.     case S_IFRLNK:            /* Remote link */
  644.     {
  645.         int size;
  646.         char linknamebuf[MAXPATHLEN+1]; /* +1 for null */
  647.  
  648.         hstat.st_size = 0;        /* Force 0 size on symlink */
  649.         header = start_header(p, &hstat);
  650.         if (header == NULL)
  651.             goto badfile;
  652.         size = readlink(p,linknamebuf, NAMSIZ+1);
  653.         if (size < 0)
  654.             goto badperror;
  655.         linknamebuf[size] = '\0';
  656.         header->header.linkflag = LF_RMTLINK;
  657.         /* 
  658.          * BSD tar requires that the link name have a trailing 
  659.          * null.  See the comments in start_header.
  660.          */
  661.         if (size < NAMSIZ) {
  662.             strcpy(header->header.linkname, linknamebuf);
  663.             finish_header(header);    /* Nothing more to do to it */
  664.         } else if (!f_long_names) {
  665.             msg("%s: remote link too long\n", p);
  666.             break;
  667.         } else {
  668.             size = readlink(p, linknamebuf, MAXPATHLEN);
  669.             linknamebuf[size] = '\0';
  670.             header->header.isextended |= XH_LINKNAME;
  671.             strcpy(header->header.linkname,
  672.                    "LINK_TOO_LONG--CHECK_EXTENDED_HEADER");
  673.             finish_header(header);
  674.             copy_long_name(linknamebuf, XH_LINKNAME);
  675.         }
  676.     }
  677.         break;
  678. #endif
  679.  
  680. #ifdef S_IFPDEV                         /* Psuedo device */
  681.     case S_IFPDEV:
  682.         hstat.st_size = 0;
  683.         header = start_header(p, &hstat);
  684.         if (header == NULL) goto badfile;
  685.         header->header.linkflag = LF_PSEUDODEV;
  686.         finish_header(header);
  687.         break;
  688. #endif
  689.  
  690.     case S_IFDIR:            /* Directory */
  691.         {
  692.         register DIR *dirp;
  693.         register struct direct *d;
  694. #ifdef ALLOW_LONG_NAMES        
  695.         char namebuf[MAXPATHLEN+2];
  696. #else        
  697.         char namebuf[NAMSIZ+2];
  698. #endif        
  699.         register int len;
  700.         int our_device = hstat.st_dev;
  701.  
  702.         /* Build new prototype name */
  703.         strncpy(namebuf, p, sizeof (namebuf));
  704.         len = strlen(namebuf);
  705.         while (len >= 1 && '/' == namebuf[len-1]) 
  706.             len--;            /* Delete trailing slashes */
  707.         namebuf[len++] = '/';        /* Now add exactly one back */
  708.         namebuf[len] = '\0';        /* Make sure null-terminated */
  709.  
  710.         /*
  711.          * Output directory header record with permissions
  712.          * FIXME, do this AFTER files, to avoid R/O dir problems?
  713.          * If old archive format, don't write record at all.
  714.          */
  715.         if (!f_oldarch) {
  716.             hstat.st_size = 0;    /* Force 0 size on dir */
  717.             /*
  718.              * If people could really read standard archives,
  719.              * this should be:        (FIXME)
  720.             header = start_header(f_standard? p: namebuf, &hstat);
  721.              * but since they'd interpret LF_DIR records as
  722.              * regular files, we'd better put the / on the name.
  723.              */
  724.             header = start_header(namebuf, &hstat);
  725.             if (header == NULL)
  726.                 goto badfile;    /* eg name too long */
  727.  
  728.             if (f_gnudump)
  729.                 header->header.linkflag = LF_DUMPDIR;
  730.             else if (f_standard)
  731.                 header->header.linkflag = LF_DIR;
  732.  
  733.             /* If we're gnudumping, we aren't done yet so don't close it. */
  734.             if(!f_gnudump)
  735.                 finish_header(header);    /* Done with directory header */
  736.         }
  737.  
  738.         /* Hack to remove "./" from the front of all the file names */
  739.         if (len == 2 && namebuf[0] == '.' && namebuf[1]=='/') {
  740.             len = 0;
  741.         }
  742.  
  743.         if(f_gnudump) {
  744.             int sizeleft;
  745.             int totsize;
  746.             int bufsize;
  747.             union record *start;
  748.             int count;
  749.             char *buf,*p_buf;
  750.  
  751.             buf=gnu_list_name->dir_contents; /* FOO */
  752.             totsize=0;
  753.             for(p_buf=buf;*p_buf;) {
  754.                 int tmp;
  755.  
  756.                 tmp=strlen(p_buf)+1;
  757.                 totsize+=tmp;
  758.                 p_buf+=tmp;
  759.             }
  760.             totsize++;
  761.             to_oct((long)totsize,1+12,header->header.size);
  762.             finish_header(header);
  763.             p_buf=buf;
  764.             sizeleft=totsize;
  765.             while(sizeleft>0) {
  766.                 if(f_multivol) {
  767.                     save_name=p;
  768.                     save_sizeleft=sizeleft;
  769.                     save_totsize=totsize;
  770.                 }
  771.                 start=findrec();
  772.                 bufsize=endofrecs()->charptr - start->charptr;
  773.                 if(sizeleft<bufsize) {
  774.                     bufsize=sizeleft;
  775.                     count=bufsize%RECORDSIZE;
  776.                     if(count)
  777.                         bzero(start->charptr+sizeleft,RECORDSIZE-count);
  778.                 }
  779.                 bcopy(p_buf,start->charptr,bufsize);
  780.                 sizeleft-=bufsize;
  781.                 p_buf+=bufsize;
  782.                 userec(start+(bufsize-1)/RECORDSIZE);
  783.             }
  784.             if(f_multivol)
  785.                 save_name = 0;
  786.             break;
  787.         }
  788.  
  789.         /* Now output all the files in the directory */
  790. #ifdef ALLOW_NO_RECURSE
  791.         if (f_no_recurse) {
  792.             break;        /* Unless the cmdline said not to */
  793.         }
  794. #endif        
  795.         errno = 0;
  796.         dirp = opendir(p);
  797.         if (!dirp) {
  798.             if (errno) {
  799.                 msg_perror ("can't open directory %s",p);
  800.             } else {
  801.                 msg("error opening directory %s",
  802.                     p);
  803.             }
  804.             break;
  805.         }
  806.  
  807.         /* Should speed this up by cd-ing into the dir, FIXME */
  808.         while (NULL != (d=readdir(dirp))) {
  809.             /* Skip . and .. */
  810.             if(is_dot_or_dotdot(d->d_name))
  811.                 continue;
  812. #ifdef ALLOW_LONG_NAMES
  813.             if (DP_NAMELEN(d) + len >= MAXPATHLEN) {
  814. #else                
  815.             if (DP_NAMELEN(d) + len >= NAMSIZ) {
  816. #endif                
  817.                 msg("file name %s%s too long\n", 
  818.                     namebuf, d->d_name);
  819.                 continue;
  820.             }
  821.             strcpy(namebuf+len, d->d_name);
  822.             if(f_exclude && check_exclude(namebuf))
  823.                 continue;
  824.             dump_file(namebuf, our_device);
  825.         }
  826.  
  827.         closedir(dirp);
  828.     }
  829.         break;
  830.  
  831. #ifdef S_IFCHR
  832.     case S_IFCHR:            /* Character special file */
  833.         type = LF_CHR;
  834.         goto easy;
  835. #endif
  836.  
  837. #ifdef S_IFBLK
  838.     case S_IFBLK:            /* Block     special file */
  839.         type = LF_BLK;
  840.         goto easy;
  841. #endif
  842.  
  843. #if defined (sprite) && defined (S_IFSOCK)
  844.     case S_IFSOCK:
  845.         /*
  846.          * Fall through and do a named pipe.  The Sprite compatible
  847.          * stat routine maps Sprite named pipes to S_IFSOCK.
  848.          */
  849. #endif
  850. #ifdef S_IFIFO
  851.     case S_IFIFO:            /* Fifo      special file */
  852.  
  853.         type = LF_FIFO;
  854. #endif
  855.  
  856.     easy:
  857.         if (!f_standard) goto unknown;
  858.  
  859.         hstat.st_size = 0;        /* Force 0 size */
  860.         header = start_header(p, &hstat);
  861.         if (header == NULL) goto badfile;    /* eg name too long */
  862.  
  863.         header->header.linkflag = type;
  864.         if (type != LF_FIFO) {
  865.             to_oct((long) major(hstat.st_rdev), 8,
  866.                 header->header.devmajor);
  867.             to_oct((long) minor(hstat.st_rdev), 8,
  868.                 header->header.devminor);
  869.         }
  870.  
  871.         finish_header(header);
  872.         break;
  873.  
  874.     default:
  875.     unknown:
  876.         msg("%s: Unknown file type; file ignored.\n", p);
  877.         break;
  878.     }
  879. }
  880.  
  881. int
  882. finish_sparse_file(fd, sizeleft, fullsize, name)
  883.     int    fd;
  884.     long     *sizeleft,
  885.         fullsize;
  886.     char    *name;
  887. {
  888.     union record    *start;
  889.     char        tempbuf[RECORDSIZE];
  890.     int        bufsize,
  891.             sparse_ind = 0,
  892.             count;
  893.     long        pos;
  894.  
  895.  
  896.  
  897.     while (*sizeleft > 0) {
  898.         start = findrec();
  899.         bzero(start->charptr, RECORDSIZE);
  900.         bufsize = sparsearray[sparse_ind].numbytes;
  901.         if (!bufsize) {  /* we blew it, maybe */
  902.                 fprintf(stderr, "Wrote %ld of %ld bytes to file %s\n",
  903.                        fullsize - *sizeleft, fullsize, name);
  904.             break;
  905.         }
  906.         pos = lseek(fd, sparsearray[sparse_ind++].offset, 0);
  907.         /* 
  908.          * If the number of bytes to be written here exceeds
  909.          * the size of the temporary buffer, do it in steps.
  910.          */
  911.         while (bufsize > RECORDSIZE) {
  912. /*            if (amt_read) {
  913.                 count = read(fd, start->charptr+amt_read, RECORDSIZE-amt_read);
  914.                 bufsize -= RECORDSIZE - amt_read;
  915.                 amt_read = 0;
  916.                 userec(start);
  917.                 start = findrec();
  918.                 bzero(start->charptr, RECORDSIZE);
  919.             }*/
  920.             /* store the data */
  921.             count = read(fd, start->charptr, RECORDSIZE);
  922.             if (count < 0)     {
  923.                 msg_perror("read error at byte %ld, reading %d bytes, in file %s", 
  924.                         fullsize - *sizeleft, bufsize, name);
  925.                 return 1;
  926.             }            
  927.             bufsize -= count;
  928.             *sizeleft -= count;
  929.             userec(start);
  930.             start = findrec();
  931.             bzero(start->charptr, RECORDSIZE);
  932.         }
  933.  
  934.  
  935.         clear_buffer(tempbuf);
  936.         count = read(fd, tempbuf, bufsize);
  937.         bcopy(tempbuf, start->charptr, RECORDSIZE);
  938.         if (count < 0)     {
  939.             msg_perror("read error at byte %ld, reading %d bytes, in file %s", 
  940.                     fullsize - *sizeleft, bufsize, name);
  941.             return 1;
  942.         }
  943. /*        if (amt_read >= RECORDSIZE) {
  944.             amt_read = 0;
  945.             userec(start+(count-1)/RECORDSIZE);
  946.             if (count != bufsize) {
  947.                 msg("file %s shrunk by %d bytes, padding with zeros.\n", name, sizeleft);
  948.                 return 1;
  949.             }
  950.             start = findrec();
  951.         } else 
  952.             amt_read += bufsize;*/
  953.         *sizeleft -= count;
  954.         userec(start);
  955.  
  956.     }
  957. /*    userec(start+(count-1)/RECORDSIZE);*/
  958.     return 0;
  959.  
  960. }
  961.  
  962. init_sparsearray()
  963. {
  964.     register int i;
  965.  
  966.     for (i = 0; i < sp_array_size; i++) {
  967.         sparsearray[i].offset = 0;
  968.         sparsearray[i].numbytes = 0;
  969.     }
  970. }
  971.  
  972.  
  973.  
  974. /*
  975.  * Okay, we've got a sparse file on our hands -- now, what we need to do is
  976.  * make a pass through the file and carefully note where any data is, i.e.,
  977.  * we want to find how far into the file each instance of data is, and how
  978.  * many bytes are there.  We store this information in the sparsearray,
  979.  * which will later be translated into header information.  For now, we use
  980.  * the sparsearray as convenient storage.
  981.  *
  982.  * As a side note, this routine is a mess.  If I could have found a cleaner
  983.  * way to do it, I would have.  If anyone wants to find a nicer way to do
  984.  * this, feel free.
  985.  */
  986. int
  987. deal_with_sparse(name, header, nulls_at_end)
  988.     char        *name;
  989.     union record     *header;
  990.  
  991. {
  992.     long    numbytes = 0;
  993.     long    offset = 0;
  994.     int    fd;
  995.     int    start,
  996.         end;
  997.     int    end_nulls = 0;
  998.     int    sparse_ind = 0,
  999.         cc;
  1000.     char    buf[RECORDSIZE];
  1001.     int     amidst_data = 0;
  1002.  
  1003.     header->header.isextended = 0;
  1004.     /* 
  1005.      * Can't open the file -- this problem will be caught later on,
  1006.      * so just return.
  1007.      */
  1008.     if ((fd = open(name, O_RDONLY)) < 0)
  1009.         return;
  1010.  
  1011.     sp_array_size = 10;
  1012.     /* 
  1013.      * Make room for our scratch space -- initially is 10 elts long
  1014.      */
  1015.     sparsearray = (struct sp_array *) malloc(sp_array_size * sizeof(struct sp_array));
  1016.  
  1017.     init_sparsearray();
  1018.     clear_buffer(buf);
  1019.  
  1020.     while ((cc = read(fd, buf, sizeof buf)) != 0) {
  1021.  
  1022.         if (sparse_ind > sp_array_size-1) {
  1023.  
  1024.         /*
  1025.          * realloc the scratch area, since we've run out of room --
  1026.          */
  1027.             sparsearray = (struct sp_array *) 
  1028.                     realloc(sparsearray,
  1029.                         2 * sp_array_size * (sizeof(struct sp_array)));
  1030.             sp_array_size *= 2;
  1031.         }
  1032.         if (cc == sizeof buf) {
  1033.             if (zero_record(buf)) {
  1034.                 if (amidst_data) {
  1035.                     sparsearray[sparse_ind++].numbytes
  1036.                         = numbytes;
  1037.                     amidst_data = 0;
  1038.                     numbytes = 0;
  1039.                 }
  1040.                 offset += cc;
  1041.             } else {  /* !zero_record(buf) */
  1042.                 if (!amidst_data) {
  1043.                         amidst_data = 1;
  1044.                     where_is_data(&start, &end, buf);
  1045.                     numbytes += end - start;
  1046.                     offset += start;
  1047.                     sparsearray[sparse_ind].offset = offset;
  1048.                 } else
  1049.                     numbytes += cc;
  1050.                 offset += cc;
  1051.             }
  1052.         } else if (cc < sizeof buf) {
  1053.             if (!zero_record(buf)) {
  1054.                 if (!amidst_data) {
  1055.                     amidst_data = 1;
  1056.                     where_is_data(&start, &end, buf);
  1057.                     /* In case there are nulls at the 
  1058.                        end that we need to remember */
  1059.                     if (end < cc)
  1060.                         end = cc;
  1061.                     numbytes += start - end;
  1062.                     offset += start;
  1063. /*                    end_nulls = RECORDSIZE - end;*/
  1064.                 } else {
  1065.                     numbytes += cc;
  1066. /*                    end_nulls = RECORDSIZE - end;*/
  1067.                 }
  1068.                 sparsearray[sparse_ind].numbytes = numbytes;
  1069.             } /* else
  1070.                 end_nulls = cc;*/
  1071.         }
  1072.         clear_buffer(buf);
  1073.     }
  1074.     if (numbytes)
  1075.             sparsearray[sparse_ind].numbytes = numbytes;
  1076.     close(fd);
  1077. /*    printf("%d\n", end_nulls);
  1078.     *nulls_at_end = end_nulls;*/
  1079.  
  1080.     return sparse_ind;
  1081. }
  1082.  
  1083. /* 
  1084.  * Just zeroes out the buffer so we don't confuse ourselves with leftover
  1085.  * data.
  1086.  */
  1087. clear_buffer(buf)
  1088.     char    *buf;
  1089. {
  1090.     register int     i;
  1091.  
  1092.     for (i = 0; i < RECORDSIZE; i++)
  1093.         buf[i] = '\0';
  1094. }
  1095.  
  1096. /* 
  1097.  * JK - 
  1098.  * This routine takes a character array, and tells where within that array
  1099.  * the data can be found.  It skips over any zeros, and sets the first
  1100.  * non-zero point in the array to be the "start", and continues until it
  1101.  * finds non-data again, which is marked as the "end."  This routine is 
  1102.  * mainly for 1) seeing how far into a file we must lseek to data, given
  1103.  * that we have a sparse file, and 2) determining the "real size" of the
  1104.  * file, i.e., the number of bytes in the sparse file that are data, as
  1105.  * opposed to the zeros we are trying to skip.
  1106.  */
  1107. where_is_data(from, to, buffer)
  1108.     int    *from,
  1109.         *to;
  1110.     char    *buffer;
  1111. {
  1112.     register int    i = 0;
  1113.     register int    save_to = *to;
  1114.     int    amidst_data = 0;
  1115.  
  1116.  
  1117.     while (!buffer[i])
  1118.         i++;
  1119.     *from = i;
  1120.  
  1121.     if (*from < 16)    /* don't bother */
  1122.         *from = 0;
  1123.     /* keep going to make sure there isn't more real
  1124.        data in this record */
  1125.     while (i < RECORDSIZE) {
  1126.         if (!buffer[i]) {
  1127.             if (amidst_data) {
  1128.                 save_to = i;
  1129.                 amidst_data = 0;
  1130.             }
  1131.             i++;
  1132.         }
  1133.         else if (buffer[i]) {
  1134.             if (!amidst_data)
  1135.                 amidst_data = 1;
  1136.             i++;
  1137.         }
  1138.     }
  1139.     if (i == RECORDSIZE)
  1140.         *to = i;
  1141.     else
  1142.         *to = save_to;
  1143.  
  1144. }
  1145.  
  1146. /*
  1147.  * Takes a recordful of data and basically cruises through it to see if
  1148.  * it's made *entirely* of zeros, returning a 0 the instant it finds
  1149.  * something that is a non-zero, i.e., useful data.
  1150.  */
  1151. zero_record(buffer)
  1152.     char    *buffer;
  1153. {
  1154.     register int    i;
  1155.  
  1156.     for (i = 0; i < RECORDSIZE; i++)
  1157.         if (buffer[i] != '\000')
  1158.             return 0;
  1159.     return 1;
  1160. }
  1161.  
  1162. find_new_file_size(filesize, highest_index)
  1163.     int    *filesize;
  1164.     int    highest_index;
  1165. {
  1166.     register int     i;
  1167.  
  1168.     *filesize = 0;
  1169.     for (i = 0; sparsearray[i].numbytes && i <= highest_index; i++)
  1170.         *filesize += sparsearray[i].numbytes;
  1171. }
  1172.  
  1173. /*
  1174.  * Make a header block for the file  name  whose stat info is  st .
  1175.  * Return header pointer for success, NULL if the name is too long.
  1176.  */
  1177. union record *
  1178. start_header(name, st)
  1179.     char    *name;
  1180.     register struct stat *st;
  1181. {
  1182.     register union record *header;
  1183.  
  1184.     header = (union record *) findrec();
  1185.     bzero(header->charptr, sizeof(*header)); /* XXX speed up */
  1186.  
  1187.     header->header.hdr_magic = HDR_MAGIC;
  1188.  
  1189.     /*
  1190.      * Check the file name and put it in the record.
  1191.      */
  1192. #ifdef MSDOS
  1193.     if(name[1]==':') {
  1194.         static int warned_once = 0;
  1195.         name+=2;
  1196.         if(!warned_once++) {
  1197.             msg("Removing drive spec from names in the archive");
  1198.         }
  1199.     }
  1200. #endif
  1201.     while (!f_absolute_paths && '/' == *name) {
  1202.         static int warned_once = 0;
  1203.  
  1204.         name++;                /* Force relative path */
  1205.         if (!warned_once++) {
  1206.             msg("Removing leading / from absolute path names in the archive.");
  1207.         }
  1208.     }
  1209.     /* 
  1210.      * Posix lets the name take up all NAMSIZ characters, but BSD tar 
  1211.      * requires a trailing null.  We can't pretend to be Posix 
  1212.      * compliant for other reasons, so let's at least try to be
  1213.      * compatible with BSD.
  1214.      */
  1215.     if (strlen(name) < NAMSIZ) {
  1216.         strcpy(header->header.name, name);
  1217.     } else if (!f_long_names) {
  1218.         msg("%s: name too long\n", name);
  1219.         return NULL;
  1220.     } else {
  1221.         int size;
  1222.         static long unique;
  1223.         
  1224.         header->header.isextended |= XH_FILENAME;
  1225.         size = strlen(name);
  1226.         if (size >= MAXPATHLEN) {
  1227.             msg("%s: file name exceeds MAXPATHLEN\n", name);
  1228.             return NULL;
  1229.         }
  1230.         sprintf(header->header.name, "/tmp/TAR.NAME_TOO_LONG.%08ld",
  1231.             ++unique);
  1232.         strcpy(longname, name);
  1233.     }
  1234.  
  1235.     to_oct((long) (st->st_mode & ~S_IFMT),
  1236.                     8,  header->header.mode);
  1237.     to_oct((long) st->st_uid,    8,  header->header.uid);
  1238.     to_oct((long) st->st_gid,    8,  header->header.gid);
  1239.     to_oct((long) st->st_size,    1+12, header->header.size);
  1240.     to_oct((long) st->st_mtime,    1+12, header->header.mtime);
  1241.     /* header->header.linkflag is left as null */
  1242.     if(f_gnudump) {
  1243.         to_oct((long) st->st_atime, 1+12, header->header.atime);
  1244.         to_oct((long) st->st_ctime, 1+12, header->header.ctime);
  1245.     }
  1246.  
  1247. #ifndef NONAMES
  1248.     /* Fill in new Unix Standard fields if desired. */
  1249.     if (f_standard) {
  1250.         header->header.linkflag = LF_NORMAL;    /* New default */
  1251.         strcpy(header->header.magic, TMAGIC);    /* Mark as Unix Std */
  1252.         finduname(header->header.uname, st->st_uid);
  1253.         findgname(header->header.gname, st->st_gid);
  1254.     }
  1255. #endif
  1256.     return header;
  1257. }
  1258.  
  1259. /* 
  1260.  * Finish off a filled-in header block and write it out.
  1261.  * We also print the file name and/or full info if verbose is on.
  1262.  * 
  1263.  * Note: this code should be able to handle Posix names (no terminating 
  1264.  * null in the header).
  1265.  */
  1266. void
  1267. finish_header(header)
  1268.     register union record *header;
  1269. {
  1270.     register int    i, sum;
  1271.     register char    *p;
  1272.     void bcopy();
  1273.     char shortname[NAMSIZ+1]; /* copy from header; +1 for null */
  1274.  
  1275.     bcopy(CHKBLANKS, header->header.chksum, sizeof(header->header.chksum));
  1276.  
  1277.     sum = 0;
  1278.     p = header->charptr;
  1279.     for (i = sizeof(*header); --i >= 0; ) {
  1280.         /*
  1281.          * We can't use unsigned char here because of old compilers,
  1282.          * e.g. V7.
  1283.          */
  1284.         sum += 0xFF & *p++;
  1285.     }
  1286.  
  1287.     /*
  1288.      * Fill in the checksum field.  It's formatted differently
  1289.      * from the other fields:  it has [6] digits, a null, then a
  1290.      * space -- rather than digits, a space, then a null.
  1291.      * We use to_oct then write the null in over to_oct's space.
  1292.      * The final space is already there, from checksumming, and
  1293.      * to_oct doesn't modify it.
  1294.      *
  1295.      * This is a fast way to do:
  1296.      * (void) sprintf(header->header.chksum, "%6o", sum);
  1297.      */
  1298.     to_oct((long) sum,    8,  header->header.chksum);
  1299.     header->header.chksum[6] = '\0';    /* Zap the space */
  1300.  
  1301.     userec(header);
  1302.  
  1303.     if (f_verbose) {
  1304.         /* These globals are parameters to print_header, sigh */
  1305.         head = header;
  1306.         /* hstat is already set up */
  1307.         head_standard = f_standard;
  1308.         if (current_filename != NULL) {
  1309.             free(current_filename);
  1310.         }
  1311.         if (header->header.isextended & XH_FILENAME) {
  1312.             current_filename = strdup(longname);
  1313.         } else {
  1314.             strncpy(shortname, head->header.name, NAMSIZ);
  1315.             shortname[NAMSIZ] = '\0';
  1316.             current_filename = strdup(shortname);
  1317.         }
  1318.         /* 
  1319.          * XXX We don't have the link name, but that's okay as long 
  1320.          * as print_header doesn't need it, which is true if 
  1321.          * f_verbose == 1.
  1322.          */
  1323.         assert(f_verbose == 1);
  1324.         print_header();
  1325.     }
  1326.     if (!f_long_names) {
  1327.         assert((header->header.isextended &
  1328.             (XH_FILENAME|XH_LINKNAME)) == 0);
  1329.     } else {
  1330.         if (header->header.isextended & XH_FILENAME) {
  1331.             copy_long_name(longname, XH_FILENAME);
  1332.         }
  1333.     }
  1334.     return;
  1335. }
  1336.  
  1337. /*
  1338.  * Quick and dirty octal conversion.
  1339.  * Converts long "value" into a "digs"-digit field at "where",
  1340.  * including a trailing space and room for a null.  "digs"==3 means
  1341.  * 1 digit, a space, and room for a null.
  1342.  *
  1343.  * We assume the trailing null is already there and don't fill it in.
  1344.  * This fact is used by start_header and finish_header, so don't change it!
  1345.  *
  1346.  * This should be equivalent to:
  1347.  *    (void) sprintf(where, "%*lo ", digs-2, value);
  1348.  * except that sprintf fills in the trailing null and we don't.
  1349.  */
  1350. void
  1351. to_oct(value, digs, where)
  1352.     register long    value;
  1353.     register int    digs;
  1354.     register char    *where;
  1355. {
  1356.  
  1357.     --digs;                /* Trailing null slot is left alone */
  1358.     where[--digs] = ' ';        /* Put in the space, though */
  1359.  
  1360.     /* Produce the digits -- at least one */
  1361.     do {
  1362.         where[--digs] = '0' + (char)(value & 7); /* one octal digit */
  1363.         value >>= 3;
  1364.     } while (digs > 0 && value != 0);
  1365.  
  1366.     /* Leading spaces, if necessary */
  1367.     while (digs > 0)
  1368.         where[--digs] = ' ';
  1369.  
  1370. }
  1371.  
  1372.  
  1373. /*
  1374.  * Write the EOT record(s).
  1375.  * We actually zero at least one record, through the end of the block.
  1376.  * Old tar writes garbage after two zeroed records -- and PDtar used to.
  1377.  */
  1378. write_eot()
  1379. {
  1380.     union record *p;
  1381.     int bufsize;
  1382.     void bzero();
  1383.  
  1384.     p = findrec();
  1385.     bufsize = endofrecs()->charptr - p->charptr;
  1386.     bzero(p->charptr, bufsize);
  1387.     userec(p);
  1388. }
  1389.  
  1390.  
  1391. static int
  1392. copy_long_name(name, type)
  1393.     char *name;
  1394.     int type;
  1395. {
  1396.     int size;
  1397.     union record *exhdr;
  1398.  
  1399.     assert(type == XH_FILENAME || type == XH_LINKNAME);
  1400.     size = strlen(name);
  1401.     assert(size >= NAMSIZ);
  1402.     assert(size <= MAXPATHLEN);
  1403.     for (;;) {
  1404.     assert(strlen(name) == size);
  1405.     exhdr = findrec();
  1406.     if (exhdr == NULL) {
  1407.         return 0;        /* XXX nobody actually looks at this number */
  1408.     }
  1409.  
  1410.     /* 
  1411.      * Make sure that the string will be null-terminated
  1412.      */
  1413.     bzero(exhdr, sizeof(exhdr));
  1414.  
  1415.     exhdr->ext_hdr.xh_type = type;
  1416.     exhdr->ext_hdr.xh_magic = XH_MAGIC;
  1417.     strncpy(exhdr->ext_hdr.xh_namebuf, name,
  1418.         sizeof(exhdr->ext_hdr.xh_namebuf));
  1419.     if (size >= sizeof(exhdr->ext_hdr.xh_namebuf)) {
  1420.         size -= sizeof(exhdr->ext_hdr.xh_namebuf);
  1421.         name += sizeof(exhdr->ext_hdr.xh_namebuf);
  1422.         exhdr->ext_hdr.xh_isextended |= type;
  1423.         userec(exhdr);
  1424.         continue;
  1425.     } else {
  1426.         exhdr->ext_hdr.xh_isextended = 0;
  1427.         userec(exhdr);
  1428.         return 1;
  1429.     }
  1430.     }
  1431. }
  1432.  
  1433. @
  1434.  
  1435.  
  1436. 1.4
  1437. log
  1438. @Changes for long file names; use file header magic number.  
  1439. (Mike checking in for Bob).  
  1440. @
  1441. text
  1442. @d26 2
  1443. d33 1
  1444. a204 1
  1445.     int sparse_ind = 0;
  1446. d291 5
  1447. a295 1
  1448. #ifdef ALLOW_LONG_NAMES
  1449. d297 7
  1450. a303 2
  1451.                     strcpy(header->header.linkname,
  1452.                     link_name);
  1453. d305 5
  1454. a309 5
  1455.                     header->header.isextended |= XH_LINKNAME;
  1456.                     strcpy(header->header.linkname,
  1457.                       "LINK_TOO_LONG--CHECK_EXTENDED_HEADER");
  1458.                     finish_header(header);
  1459.                     copy_long_name(link_name, XH_LINKNAME);
  1460. a310 5
  1461. #else
  1462.                 strcpy(header->header.linkname,
  1463.                     link_name);
  1464.                 finish_header(header);
  1465. #endif
  1466. a463 1
  1467.             int     arraybound = SPARSE_EXT_HDR;
  1468. d564 1
  1469. d568 6
  1470. a573 1
  1471.         if (header == NULL) goto badfile;
  1472. d575 9
  1473. a583 9
  1474.         size = readlink(p, header->header.linkname, NAMSIZ);
  1475.         if (size < 0) goto badperror;
  1476.         if (size == NAMSIZ) {
  1477. #ifdef ALLOW_LONG_NAMES
  1478.             char linknamebuf[MAXPATHLEN];
  1479.  
  1480.             size = readlink(p, linknamebuf, MAXPATHLEN);
  1481.             if (size == MAXPATHLEN) {
  1482.             msg("symbolic link %s exceeds MAXPATHLEN\n", p);
  1483. a584 10
  1484.             }
  1485.             header->header.isextended |= XH_LINKNAME;
  1486.             strcpy(header->header.linkname,
  1487.             "LINK_TOO_LONG--CHECK_EXTENDED_HEADER");
  1488.             finish_header(header);
  1489.             copy_long_name(linknamebuf, XH_LINKNAME);
  1490. #else
  1491.             msg("symbolic link %s too long\n",p);
  1492.             break;
  1493. #endif        
  1494. d586 7
  1495. a592 2
  1496.             header->header.linkname[size] = '\0';
  1497.             finish_header(header);    /* Nothing more to do to it */
  1498. d601 1
  1499. d605 6
  1500. a610 3
  1501.         if (header == NULL) goto badfile;
  1502.         size = readlink(p, header->header.linkname, NAMSIZ);
  1503.         if (size < 0) goto badperror;
  1504. d612 9
  1505. a620 7
  1506.         if (size == NAMSIZ) {
  1507. #ifdef ALLOW_LONG_NAMES
  1508.             char linknamebuf[MAXPATHLEN];
  1509.  
  1510.             size = readlink(p, linknamebuf, MAXPATHLEN);
  1511.             if (size == MAXPATHLEN) {
  1512.             msg("remote link %s exceeds MAXPATHLEN\n", p);
  1513. a621 10
  1514.             }
  1515.             header->header.isextended |= XH_LINKNAME;
  1516.             strcpy(header->header.linkname,
  1517.             "LINK_TOO_LONG--CHECK_EXTENDED_HEADER");
  1518.             finish_header(header);
  1519.             copy_long_name(linknamebuf, XH_LINKNAME);
  1520. #else
  1521.             msg("%s: remote link too long\n", p);
  1522.             break;
  1523. #endif        
  1524. d623 7
  1525. a629 2
  1526.             header->header.linkname[size] = '\0';
  1527.             finish_header(header);    /* Nothing more to do to it */
  1528. a948 1
  1529.     long    save_offset;
  1530. a952 1
  1531.     int    current_size = hstat.st_size;
  1532. a955 1
  1533.     int    read_last_data = 0; /* did we just read the last record? */
  1534. d1164 10
  1535. a1173 12
  1536.     strcpy(header->header.name, name);
  1537.     if (header->header.name[NAMSIZ-1]) {
  1538. #ifdef ALLOW_LONG_NAMES
  1539.         char *np;
  1540.         int size;
  1541.         union record *exhdr;
  1542.         static long unique;
  1543.  
  1544.         header->header.isextended |= XH_FILENAME;
  1545.         size = strlen(name);
  1546.         if (size >= MAXPATHLEN) {
  1547.         msg("%s: file name exceeds MAXPATHLEN\n", name);
  1548. d1175 13
  1549. a1187 8
  1550.         }
  1551.         sprintf(header->header.name, "/tmp/TAR.NAME_TOO_LONG.%08ld",
  1552.         ++unique);
  1553.         strcpy(longname, name);
  1554. #else        
  1555.         msg("%s: name too long\n", name);
  1556.         return NULL;
  1557. #endif        
  1558. d1217 3
  1559. d1228 1
  1560. d1263 16
  1561. d1281 7
  1562. a1287 3
  1563. #ifdef ALLOW_LONG_NAMES
  1564.     if (header->header.isextended & XH_FILENAME) {
  1565.         copy_long_name(longname, XH_FILENAME);
  1566. a1288 3
  1567. #else
  1568.     assert((header->header.isextended & XH_FILENAME) == 0);
  1569. #endif
  1570. d1361 7
  1571. d1369 1
  1572. a1371 3
  1573.     if (exhdr == NULL) {
  1574.         return 0;
  1575.     }
  1576. @
  1577.  
  1578.  
  1579. 1.3
  1580. log
  1581. @Fixed bug in for no_recurse flag.
  1582. @
  1583. text
  1584. @d131 2
  1585. d227 1
  1586. a227 1
  1587.         && (f_new_files>1 || new_time>hstat.st_ctime)) {
  1588. d288 1
  1589. d297 1
  1590. d303 1
  1591. a304 2
  1592.                 header->header.linkflag = LF_LINK;
  1593.                 finish_header(header);
  1594. d584 3
  1595. a587 2
  1596.         header->header.linkname[size] = '\0';
  1597.         finish_header(header);        /* Nothing more to do to it */
  1598. d601 1
  1599. d620 3
  1600. a623 3
  1601.         header->header.linkname[size] = '\0';
  1602.         header->header.linkflag = LF_RMTLINK;
  1603.         finish_header(header);        /* Nothing more to do to it */
  1604. d1138 2
  1605. d1176 1
  1606. a1176 2
  1607.         finish_header(header);
  1608.         copy_long_name(name, XH_FILENAME);
  1609. d1254 7
  1610. a1260 1
  1611.  
  1612. a1263 1
  1613.  
  1614. d1283 1
  1615. a1283 1
  1616.     
  1617. @
  1618.  
  1619.  
  1620. 1.2
  1621. log
  1622. @Added support for long filenames and long symbolic linkes.
  1623. @
  1624. text
  1625. @a250 1
  1626.         regular_file:
  1627. d342 1
  1628. a342 1
  1629.         
  1630. d348 1
  1631. a348 1
  1632.           * JK - This is the test for sparseness: whether the
  1633. d634 1
  1634. a634 6
  1635. #ifdef ALLOW_NO_RECURSE
  1636.         if (f_no_recurse) {
  1637.         goto regular_file;  /* dump directory as a regular file */
  1638.         } else
  1639. #endif        
  1640.     {
  1641. d733 5
  1642. a737 4
  1643.         /* if (f_dironly)
  1644.             break;        /* Unless the cmdline said not to */
  1645.  
  1646.  
  1647. @
  1648.  
  1649.  
  1650. 1.1
  1651. log
  1652. @Initial revision
  1653. @
  1654. text
  1655. @d31 2
  1656. d125 6
  1657. d170 1
  1658. a170 1
  1659.     
  1660. d223 2
  1661. a224 2
  1662.         && new_time>hstat.st_mtime
  1663.         && (hstat.st_mode&S_IFMT)!=S_IFDIR
  1664. d251 1
  1665. d287 12
  1666. a298 1
  1667.                   strcpy(header->header.linkname,
  1668. d300 1
  1669. d376 1
  1670. a376 1
  1671.                  
  1672. d378 1
  1673. a378 1
  1674.                          
  1675. d383 3
  1676. a385 2
  1677.                 if (upperbound > SPARSE_IN_HDR-1)
  1678.                      header->header.isextended++;
  1679. d395 1
  1680. a395 1
  1681.                          header->header.realsize);
  1682. d434 1
  1683. a434 1
  1684.         
  1685. a449 1
  1686.         isextended = header->header.isextended;
  1687. d458 1
  1688. a458 1
  1689.             
  1690. d460 1
  1691. a460 1
  1692.             
  1693. d463 1
  1694. d468 2
  1695. a469 2
  1696.                      1+12,
  1697.                     exhdr->ext_hdr.sp[i].numbytes);
  1698. d471 2
  1699. a472 2
  1700.                      1+12,
  1701.                     exhdr->ext_hdr.sp[i].offset);
  1702. d480 1
  1703. a480 1
  1704.                 exhdr->ext_hdr.isextended++;
  1705. d483 1
  1706. a483 1
  1707.                 
  1708. d491 1
  1709. a491 1
  1710.             
  1711. d500 1
  1712. a500 1
  1713.                 
  1714. d561 35
  1715. d599 6
  1716. a604 1
  1717.             msg("symbolic link %s too long\n",p);
  1718. d606 10
  1719. d618 1
  1720. a618 1
  1721.         header->header.linkflag = LF_SYMLINK;
  1722. d624 10
  1723. d635 5
  1724. d643 3
  1725. d647 1
  1726. d742 1
  1727. a742 1
  1728.         
  1729. d760 3
  1730. a762 1
  1731.  
  1732. d764 1
  1733. d791 7
  1734. d800 1
  1735. a800 1
  1736.         
  1737. d853 1
  1738. a853 1
  1739.              }
  1740. d938 1
  1741. a938 1
  1742.     
  1743. d953 1
  1744. a953 1
  1745.     
  1746. d961 1
  1747. a961 1
  1748.         
  1749. d972 1
  1750. a972 1
  1751.             
  1752. d974 1
  1753. a974 1
  1754.         
  1755. d980 1
  1756. a980 1
  1757.                          2 * sp_array_size * (sizeof(struct sp_array)));
  1758. d1067 1
  1759. a1067 1
  1760.     
  1761. d1094 1
  1762. a1094 1
  1763.         
  1764. d1123 1
  1765. a1123 1
  1766.     
  1767. d1160 10
  1768. a1169 1
  1769.         msg("%s: name too long\n", name);
  1770. d1171 9
  1771. d1310 39
  1772. @
  1773.